home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / vol7n1.arc / HELP.ASM < prev    next >
Assembly Source File  |  1987-12-08  |  33KB  |  742 lines

  1. ;                       Help.asm
  2. ;                Resident help facility
  3. ; Format:  HELP filespec [... filespec][/Nn][/P][/Hn] | [/U]
  4. ; defaults: pages = 4; hot key = Alt H
  5.  
  6. CODE SEGMENT                           ;********************************;
  7. ASSUME CS:CODE,DS:CODE                 ;*                              *;
  8. ORG 100H                               ;*  Requires MASM 2.0 or later  *;
  9.                                        ;*     Remember to EXE2BIN      *;
  10. START:         JMP    BEGINNING        ;*                              *;
  11.                                        ;********************************;
  12.  
  13. ;              DATA AREA
  14. ;              ---------
  15. COPYRIGHT      DB     "HELP 1.0 (c) 1987 Ziff Communications Co.",13,10
  16.                DB     "Successfully installed",13,10
  17. ALT_COMBO      DB     "Press Alt H to activate",10,0,26
  18.  
  19. PROGRAMMER     DB     "Michael J. Mefford"
  20.  
  21. OLD_KEYBOARD   DD     ?
  22. CRT_COLS       DW     ?
  23. STATUS_REG     DW     ?
  24. SCREEN_SEG     DW     0B000H
  25. LINE_COUNT     DB     25
  26. IMMEDIATE_FLAG DB     0
  27. BUSY           DB     0
  28.  
  29. IMMEDIATE      DW     POP_IT
  30. DATA_SEG       DW     ?
  31. DATA_INT       DB     0
  32. INSTALLED_FLAG DB     0
  33. POPUP_FLAG     DB     0
  34. HOT_KEY        DB     35
  35.  
  36. FILENAME       DW     ?
  37. ERROR_LEVEL    DB     0
  38.  
  39. CURRENT_PAGE   DB     1
  40. RESERVED_PAGES DB     4
  41. ACTIVE_PAGES   DB     0
  42. PAGE_COUNT     DB     0
  43. DELIMITERS     DB     9,32,13,44,";","/"
  44.  
  45. SYNTAX LABEL BYTE
  46. DB  10,"Usage:  HELP filespec [... filespec][/Nn][/Hn][/P] | [/U]",13,10,10
  47. DB     "/Nn where n = number of reserved pages (1-14); default = 4",13,10
  48. DB     "/Hn where n = Alt hot key combo (A-Z,0-9,",34,45,34,44,34,61,34
  49. DB     "); default = H",13,10
  50. DB     "/P  = immediate pop-up",13,10
  51. DB     "/U  = uninstall",13,10,10
  52. DB     "Use: PgUp PgDn Home End to navigate through HELP",13,10
  53. DB     5 DUP(32),"ESC or hot key to exit",10,0
  54.  
  55.  
  56. ACTIVE_MSG     DB     " active page(s)",13,10,0
  57. RESERVED_MSG   DB     " total page(s)",13,10,10,0
  58. UNLOAD_MSG     DB     10,"HELP can't be uninstalled.",13,10
  59.                DB     "Uninstall resident programs in reverse order.",10,0
  60. UNINSTALL_MSG  DB     10,"HELP uninstalled",10,0
  61. NO_FREE        DB     "Too many resident programs",0
  62. NOT_FOUND      DB     32,"not found",13,10,0
  63. NOT_ENOUGH     DB     "Not enough memory",0
  64. ALLOCATE_MSG   DB     "Memory allocation error",13,10,0
  65.  
  66. SCAN_CODES LABEL BYTE
  67.  
  68. DB 45,130,48,129,49,120,50,121,51,122,52,123,53,124
  69. DB 54,125,55,126,56,127,57,128,61,131,65,30,66,48,67
  70. DB 46,68,32,69,18,70,33,71,34,72,35,73,23,74,36,75,37
  71. DB 76,38,77,50,78,49,79,24,80,25,81,16,82,19,83,31
  72. DB 84,20,85,22,86,47,87,17,88,45,89,21,90,44
  73.  
  74. ;                          SCAN CODES FOR ALT COMBO
  75. ;
  76. ;         Code   Key      Code   Key      Code   Key       Code   Key
  77. ;           16   Q          30   A          44   Z          120   1
  78. ;           17   W          31   S          45   X          121   2
  79. ;           18   E          32   D          46   C          122   3
  80. ;           19   R          33   F          47   V          123   4
  81. ;           20   T          34   G          48   B          124   5
  82. ;           21   Y          35   H          49   N          125   6
  83. ;           22   U          36   J          50   M          126   7
  84. ;           23   I          37   K                          127   8
  85. ;           24   O          38   L                          128   9
  86. ;           25   P                                          129   0
  87. ;                                                           130   -
  88. ;     Default is 35 (Alt H)                                 131   =
  89.  
  90.  
  91. ;************* KEYBOARD INTERCEPTOR *************;
  92.  
  93. NEW_KEYBOARD:  STI
  94.                PUSHF                         ;Simulate an interrupt
  95.                CALL   CS:OLD_KEYBOARD        ; by pushing flags and far call.
  96.  
  97. POP_IT:        PUSHF                         ;On return save all registers
  98.                PUSH   DS                     ; that will be used.
  99.                PUSH   ES
  100.                PUSH   AX
  101.                PUSH   BX
  102.                PUSH   CX
  103.                PUSH   DX
  104.                PUSH   SI
  105.                PUSH   DI
  106.                PUSH   BP
  107.  
  108.                PUSH   CS                     ;Point to our data.
  109.                POP    DS
  110.                CLD                           ;Moves in forward direction.
  111.                MOV    AX,40H                 ;Point to ROM BIOS data area
  112.                MOV    ES,AX
  113.                MOV    AX,ES:[4AH]            ;Get number of columns on screen
  114.                MOV    CRT_COLS,AX            ; and store.
  115.                MOV    AX,ES:[63H]            ;Get base address of video card.
  116.                ADD    AX,6                   ;Convert to status register
  117.                MOV    STATUS_REG,AX          ; and store.
  118.                CMP    AX,3BAH                ;Is it mono card?
  119.                JZ     MONO                   ;If yes, use b800h.
  120.                MOV    SCREEN_SEG,0B800H      ; else point to color card.
  121. MONO:          MOV    AL,ES:[49H]            ;Retrieve video mode.
  122.                CMP    AL,3                   ;Is it text mode?
  123.                JBE    GOOD_MODE              ;If yes, OK.
  124.                CMP    AL,7
  125.                JNZ    DONE_HERE              ;Exit if graphics
  126.  
  127. GOOD_MODE:     CMP    IMMEDIATE_FLAG,1       ;Is there a pop-up request?
  128.                JZ     NOW                    ;If yes, pop-up right now.
  129.                CMP    BUSY,1                 ;If the window is already popped
  130.                JZ     DONE_HERE              ; exit Int 9 back to window.
  131.                MOV    AH,1                   ;Is an ASCII character ready?
  132.                INT    16H
  133.                JZ     DONE_HERE              ;If it's just a key release, exit.
  134.                CMP    AL,0                   ;Is it extended code?
  135.                JNZ    DONE_HERE              ;If no, exit.
  136.                CMP    AH,HOT_KEY             ;Else, see if our Alt key combo.
  137.                JZ     OPEN_WINDOW            ;If yes, open window
  138. DONE_HERE:     JMP    SHORT EXIT_KEYBOARD    ; else exit.
  139.  
  140. ;------------------------------------;
  141. ; Save screen so we can pop up HELP. ;
  142. ;------------------------------------;
  143.  
  144. OPEN_WINDOW:   MOV    AH,0                   ;Retrieve and discard hot key
  145.                INT    16H                    ; character from keyboard buffer.
  146. NOW:           MOV    BUSY,1                 ;Flag that window is open.
  147.                MOV    IMMEDIATE_FLAG,0       ;Restore immediate flag.
  148.                CALL   STORE_SCREEN           ;Store screen.
  149.  
  150. ;-----------------------------------------;
  151. ; Loop here looking for valid keystrokes. ;
  152. ;-----------------------------------------;
  153.  
  154. READ_KEY:      MOV    CL,CURRENT_PAGE        ;Get current page.
  155.                DEC    CL                     ;Adjust for starting offset.
  156.                CALL   PAGE_SIZE              ;Get offset.
  157.                MOV    SI,DX
  158.                CALL   WRITE_SCREEN           ;Update the screen.
  159.                MOV    AH,0                   ;Wait for a character.
  160.                INT    16H
  161.                CMP    AH,1                   ;Is it Esc?
  162.                JZ     EXIT_WINDOW            ;If yes, exit window.
  163.                CMP    AH,BYTE PTR HOT_KEY    ;Is it our key combo?
  164.                JZ     EXIT_WINDOW            ;If yes, exit window.
  165.  
  166.                MOV    CL,CURRENT_PAGE        ;Get current page.
  167.                CMP    AH,49H                 ;Is it PgUp?
  168.                JNZ    CK_PGDN
  169.                CMP    CL,1                   ;If yes, is it already page one?
  170.                JZ     END_KEY
  171.                DEC    CL                     ;If no, decrement page.
  172.  
  173. CK_PGDN:       CMP    AH,51H                 ;Is it PgDn?
  174.                JNZ    CK_HOME
  175.                CMP    CL,ACTIVE_PAGES        ;If yes, are we already last page?
  176.                JZ     END_KEY
  177.                INC    CL                     ;If no, increment page.
  178.  
  179. CK_HOME:       CMP    AH,47H                 ;Is it Home?
  180.                JNZ    CK_END
  181.                MOV    CL,1                   ;If yes, move to page one.
  182.  
  183. CK_END:        CMP    AH,4FH                 ;Is it End?
  184.                JNZ    END_KEY
  185.                MOV    CL,ACTIVE_PAGES        ;If yes, move to last page.
  186.  
  187. END_KEY:       MOV    CURRENT_PAGE,CL        ;Store new current page.
  188.                JMP    SHORT READ_KEY
  189.  
  190. ;----------------------------------;
  191. ; This is the window exit routine. ;
  192. ;----------------------------------;
  193.  
  194. EXIT_WINDOW:   MOV    SI,OFFSET SCREEN_BUFFER  ;Point to the stored screen
  195.                CALL   WRITE_SCREEN             ; and restore the screen.
  196.                MOV    IMMEDIATE_FLAG,0       ;Reset the pop-up flag.
  197.                MOV    BUSY,0                 ;Flag done with window.
  198.  
  199. EXIT_KEYBOARD: POP    BP                     ;Restore all registers.
  200.                POP    DI
  201.                POP    SI
  202.                POP    DX
  203.                POP    CX
  204.                POP    BX
  205.                POP    AX
  206.                POP    ES
  207.                POP    DS
  208.                POPF
  209.                IRET                          ;Return from interrupt.
  210.  
  211.  
  212. ;************* FILE LOADING AND INSTALL PROCEDURE *************;
  213.  
  214. BEGINNING:     CLD
  215.                PUSH   CS
  216.                POP    DATA_SEG               ;Store our segment.
  217.                CMP    SP,65533               ;Do we have 64K?
  218.                JA     CK_PARA
  219.                MOV    SI,OFFSET NOT_ENOUGH   ;If no, exit with message.
  220.                JMP    ERROR_EXIT
  221.  
  222. CK_PARA:       CMP    BYTE PTR DS:[80H],0    ;Any parameters?
  223.                JNZ    CK_FREE
  224. OPTIONS:       MOV    SI,OFFSET SYNTAX       ;If no, exit with syntax message.
  225.                JMP    ERROR_EXIT
  226.  
  227. ;----------------------------------------------------------------------;
  228. ; Check user vectors to see if we are installed or if one is available ;
  229. ;----------------------------------------------------------------------;
  230.  
  231. CK_FREE:       MOV    AL,60H - 1             ;Available vectors are 60H - 67H.
  232. FREE_USER_INT: INC    AL
  233.                MOV    AH,35H                 ;Get vector address.
  234.                INT    21H
  235.                CMP    BX,0                   ;Is offset being used?
  236.                JNZ    CK_SIGNATURE           ;If yes, see if it's us.
  237.                MOV    DX,ES
  238.                CMP    DX,0                   ;Is segment being used?
  239.                JNZ    CK_SIGNATURE           ;If yes, see if it's us.
  240.                MOV    DATA_INT,AL            ;If available, save INT number.
  241.  
  242. NEXT_USER:     CMP    AL,67H                 ;Have we checked all 7?
  243.                JNZ    FREE_USER_INT          ;If no, next one.
  244.                JMP    SHORT CK_SWITCHES
  245.  
  246. CK_SIGNATURE:  MOV    DI,BX                  ;See if INT has our signature.
  247.                MOV    SI,100H
  248.                MOV    CX,30/2
  249.                REPZ   CMPSW
  250.                JNZ    NEXT_USER              ;If yes, already installed.
  251.                MOV    DATA_SEG,ES            ;Save segment.
  252.                MOV    INSTALLED_FLAG,1
  253.  
  254. ;--------------------------------------------;
  255. ; Check the command line for switch options. ;
  256. ;--------------------------------------------;
  257.  
  258. CK_SWITCHES:   PUSH   DATA_SEG               ;First point to installed segment.
  259.                POP    ES
  260.                MOV    SI,81H                 ;First parameter.
  261.  
  262. NEXT_SWITCH:   LODSB                         ;Get a byte.
  263.                CMP    AL,13                  ;Is it carriage return?
  264.                JZ     CK_FILENAMES           ;If yes, done here.
  265.                CMP    AL,"/"                 ;Is it switch character?
  266.                JNZ    NEXT_SWITCH            ;If no, get next byte
  267.                LODSB                         ; else get switch.
  268.                CMP    AL,13                  ;Is it carriage return?
  269.                JZ     CK_FILENAMES           ;If yes, done here
  270.                CALL   CAPITALIZE             ; else capitalize.
  271.  
  272.                CMP    AL,"U"                 ;Is it "U"?
  273.                JNZ    CK_N
  274.                CMP    INSTALLED_FLAG,1       ;If yes, are we installed?
  275.                JNZ    NEXT_SWITCH
  276.                JMP    UNINSTALL              ;If yes, uninstall.
  277.  
  278. CK_N:          CMP    AL,"N"                 ;Is it "N"?
  279.                JNZ    CK_P
  280.                CMP    INSTALLED_FLAG,1       ;If yes, are we installed?
  281.                JZ     NEXT_SWITCH            ;If yes, can't change reserved.
  282.                CALL   DEC_TO_HEX             ;Else, convert decimal to hex.
  283.                CMP    BL,14                  ;Request greater than 14 pages
  284.                JA     NEXT_SWITCH            ; or equal to zero?
  285.                CMP    BL,0
  286.                JZ     NEXT_SWITCH            ;If yes, ignore.
  287.                MOV    RESERVED_PAGES,BL      ;Else, store reserved pages.
  288.                JMP    SHORT NEXT_SWITCH
  289.  
  290. CK_P:          CMP    AL,"P"                 ;Is it "P"?
  291.                JNZ    CK_H
  292.                MOV    POPUP_FLAG,1           ;If yes, flag to pop-up immediate.
  293.  
  294. CK_H:          CMP    AL,"H"                 ;Is it "H"?
  295.                JNZ    NEXT_SWITCH
  296.                LODSB
  297.                DEC    SI                     ;Adjust in case it's just CR.
  298.                CALL   CAPITALIZE
  299.                MOV    DI,OFFSET SCAN_CODES
  300.                MOV    CX,38                  ;38 possible Alt key combos.
  301.  
  302. NEXT_ALT:      SCASB                         ;Do we have a match?
  303.                JZ     GOT_ALT
  304.                INC    DI                     ;If no, bump pointer to next byte.
  305.                LOOP   NEXT_ALT
  306.                JMP    SHORT NEXT_SWITCH
  307.  
  308. GOT_ALT:       MOV    ALT_COMBO + 10,AL      ;Store Alt key.
  309.                MOV    AL,[DI]                ;Get scan code
  310.                MOV    ES:HOT_KEY,AL          ; and store.
  311.                JMP    SHORT NEXT_SWITCH
  312.  
  313. ;-----------------------------------------------------;
  314. ; This routine parses the command line for filenames. ;
  315. ;-----------------------------------------------------;
  316.  
  317. CK_FILENAMES:  MOV    SI,81H                 ;Point to first parameter.
  318. NEXT_FILENAME: CALL   CK_DELIMITER           ;Is it a delimiter?
  319.                JC     CK_CR                  ;If yes, see if end.
  320.                MOV    FILENAME,SI            ;Else, store filename start.
  321. FIND_END:      CALL   CK_DELIMITER           ;Look for delimiter to mark end.
  322.                JNC    FIND_END
  323.                PUSH   SI                     ;Save pointer and delimiter.
  324.                PUSH   AX
  325.                CALL   READ_FILE              ;Read the file in.
  326.                POP    AX
  327.                POP    SI                     ;Restore pointers.
  328.  
  329. CK_CR:         CMP    AL,13                  ;Is it carriage return?
  330.                JZ     END_FILENAMES          ;If yes, done here.
  331.                CMP    AL,"/"                 ;Is it switch character?
  332.                JNZ    NEXT_FILENAME          ;If no, get next filename.
  333. FIND_SWITCH:   CALL   CK_DELIMITER           ;Else, look for delimiter.
  334.                JNC    FIND_SWITCH
  335.                JMP    SHORT CK_CR            ;And check if carriage return.
  336.  
  337. END_FILENAMES: MOV    AL,PAGE_COUNT          ;Retrieve page count.
  338.                CMP    INSTALLED_FLAG,1       ;Are we installed?
  339.                JZ     STORE_ACTIVE           ;If yes, check pages read.
  340.                CMP    AL,RESERVED_PAGES      ;Pages read greater than reserved?
  341.                JBE    STORE_ACTIVE
  342.                MOV    RESERVED_PAGES,AL      ;If yes, store as reserved.
  343.  
  344. STORE_ACTIVE:  CMP    AL,0                   ;Did we read any pages?
  345.                JZ     CK_INSTALLED1          ;If no, check if installed.
  346.                MOV    ES:ACTIVE_PAGES,AL     ;Else, store active pages.
  347.                MOV    ES:CURRENT_PAGE,1      ;Reset the current page to one.
  348.                JMP    SHORT CK_POPUP         ;Check popup request.
  349.  
  350. CK_INSTALLED1: CMP    INSTALLED_FLAG,1       ;Are we installed?
  351.                JNZ    CK_INSTALLED2          ;If no, exit.
  352.  
  353. ;----------------------------------------;
  354. ; This routine does an immediate pop-up. ;
  355. ;----------------------------------------;
  356.  
  357. CK_POPUP:      CMP    POPUP_FLAG,1           ;Is there a popup request?
  358.                JNZ    CK_INSTALLED2          ;If no, check pages read.
  359.                MOV    ES:IMMEDIATE_FLAG,1    ;Else, flag keyboard routine.
  360.                PUSHF                         ;Simulate an interrupt.
  361.                CALL   DWORD PTR IMMEDIATE
  362.                MOV    BL,0                   ;Error level of zero.
  363.                CMP    AL,0                   ;Any pages read?
  364.                JZ     EXIT                   ;If no, done here.
  365.  
  366. ;--------------------------------------------------;
  367. ; This routine checks to see if we are to install. ;
  368. ;--------------------------------------------------;
  369.  
  370. CK_INSTALLED2: CMP    AL,0                   ;Did we fail to open a file?
  371.                MOV    SI,OFFSET SYNTAX       ;If yes, exit with syntax message.
  372.                JZ     ERROR_EXIT
  373.                PUSH   AX
  374.                MOV    CL,AL                  ;Save active pages.
  375.                MOV    DL,10
  376.                CALL   WRITE_IT               ;Display linefeed.
  377.                CALL   WRITE_NUMBER           ;Display active pages.
  378.                MOV    SI,OFFSET ACTIVE_MSG
  379.                CALL   DISPLAY_TEXT
  380.                POP    AX
  381.  
  382.                CMP    INSTALLED_FLAG,1       ;Are we already installed?
  383.                MOV    BL,ERROR_LEVEL
  384.                JZ     EXIT                   ;If yes, done here
  385. CK_INT:        CMP    DATA_INT,0             ;Did we find a free user interrupt?
  386.                JNZ    INSTALL                ;If yes, install
  387.                MOV    SI,OFFSET NO_FREE      ;Else, exit with message.
  388.  
  389. ;-------------------;
  390. ; This is the exit. ;
  391. ;-------------------;
  392.  
  393. ERROR_EXIT:    MOV    BL,1                   ;Error code of one.
  394. MSG_EXIT:      CALL   DISPLAY_TEXT
  395. EXIT:          MOV    AL,BL
  396.                MOV    AH,4CH                 ;Return with error code.
  397.                INT    21H                    ;Terminate.
  398.  
  399. ;--------------------------------;
  400. ; This is the install procedure. ;
  401. ;--------------------------------;
  402.  
  403. INSTALL:       MOV    AX,DS:[2CH]            ;Get environment segment.
  404.                MOV    ES,AX
  405.                MOV    AH,49H                 ;Free up environment.
  406.                INT    21H
  407.                MOV    SI,OFFSET ALLOCATE_MSG
  408.                JC     ERROR_EXIT             ;If error, exit with message.
  409.  
  410.                MOV    DX,100H                ;Install user interrupt as
  411.                MOV    AL,DATA_INT            ; pointer to residency.
  412.                MOV    AH,25H
  413.                INT    21H
  414.  
  415.                MOV    AX,3509H               ;Get keyboard interrupt.
  416.                INT    21H
  417.                MOV    WORD PTR OLD_KEYBOARD,BX     ;Save old interrupt.
  418.                MOV    WORD PTR OLD_KEYBOARD[2],ES
  419.  
  420.                MOV    DX,OFFSET NEW_KEYBOARD       ;Install new interrupt.
  421.                MOV    AX,2509H
  422.                INT    21H
  423.  
  424.                MOV    CL,RESERVED_PAGES      ;Display reserved pages.
  425.                CALL   WRITE_NUMBER
  426.                MOV    SI,OFFSET RESERVED_MSG
  427.                CALL   DISPLAY_TEXT
  428.  
  429.                MOV    SI,OFFSET COPYRIGHT    ;Display install message.
  430.                CALL   DISPLAY_TEXT
  431.  
  432.                CALL   PAGE_SIZE              ;Convert reserved pages to offset.
  433.                MOV    CL,4
  434.                SHR    DX,CL                  ;Convert to paragraphs.
  435.                INC    DX                     ;Round up one.
  436.                MOV    AX,3100H               ;Return error code of zero.
  437.                INT    21H                    ;Terminate but stay resident.
  438.  
  439.                ;*************;
  440.                ; SUBROUTINES ;
  441.                ;*************;
  442.  
  443. ;-----------------------------------------------;
  444. ; This subroutine uninstalls the resident help. ;
  445. ;-----------------------------------------------;
  446.  
  447. UNINSTALL:     MOV    AX,3509H               ;Get keyboard interrupt.
  448.                INT    21H
  449.                CMP    BX,OFFSET NEW_KEYBOARD ;Is the offset vector same?
  450.                MOV    SI,OFFSET UNLOAD_MSG   ;Error message if INT 9h changed.
  451.                MOV    BL,1                   ;Error code of one if fails.
  452.                JNZ    MSG_EXIT
  453.                MOV    AX,ES                  ;Is segment vector same?
  454.                CMP    AX,DATA_SEG
  455.                JNZ    MSG_EXIT               ;If no, exit with error.
  456.  
  457.                MOV    ES,DATA_SEG            ;Point to resident segment.
  458.                MOV    AH,49H                 ;And return memory to system pool.
  459.                INT    21H
  460.                MOV    SI,OFFSET ALLOCATE_MSG
  461.                JNC    DEALLOCATED            ;Display message if problem.
  462.                CALL   DISPLAY_TEXT
  463.  
  464. DEALLOCATED:   MOV    DX,ES:WORD PTR OLD_KEYBOARD      ;Restore old INT 9.
  465.                MOV    DS,ES:WORD PTR OLD_KEYBOARD[2]
  466.                MOV    AX,2509H
  467.                INT    21H
  468.  
  469.                MOV    AL,ES:DATA_INT         ;Retrieve user interrupt.
  470.                XOR    DX,DX
  471.                MOV    DS,DX                  ;Return vector to nulls.
  472.                MOV    AH,25H
  473.                INT    21H
  474.  
  475.                PUSH   CS
  476.                POP    DS
  477.                MOV    SI,OFFSET UNINSTALL_MSG    ;Display uninstall message.
  478.                MOV    BL,0                       ;Error code of zero.
  479.                JMP    MSG_EXIT                   ;And exit.
  480.  
  481. ;-----------------------------------------;
  482. ; These subroutines display the messages. ;
  483. ;-----------------------------------------;
  484.  
  485. WRITE_NUMBER:  MOV    BL,CL                  ;Retrieve number.
  486.                CMP    BL,10                  ;Is it greater than ten?
  487.                JB     ONES
  488.                MOV    DL,"1"                 ;If yes, display a one.
  489.                CALL   WRITE_IT
  490.                SUB    BL,10
  491. ONES:          MOV    DL,BL
  492.                ADD    DL,"0"                 ;Convert to decimal.
  493.                CALL   WRITE_IT               ;Display one's digit.
  494.                RET
  495.  
  496. ;----------------------------------------;
  497.  
  498. WRITE_IT:      MOV    AH,2                   ;Display byte via DOS.
  499.                INT    21H
  500.                RET
  501.  
  502. ;----------------------------------------;
  503.  
  504. DISPLAY_IT:    CALL   WRITE_IT
  505. DISPLAY_TEXT:  LODSB                         ;Get a byte
  506.                MOV    DL,AL
  507.                CMP    DL,0                   ;Zero marks end of string.
  508.                JNZ    DISPLAY_IT
  509.                RET
  510.  
  511. ;-------------------------------------------------------------;
  512. ; This subroutine opens files if there is room to store them. ;
  513. ;-------------------------------------------------------------;
  514.  
  515. READ_FILE:     CALL   CK_SPACE               ;Is there room for help?
  516.                JC     END_READ
  517.                MOV    DX,FILENAME            ;If yes, open file.
  518.                DEC    DX
  519.                MOV    AX,3D00H
  520.                INT    21H
  521.                JNC    GOT_FILE
  522.                MOV    ERROR_LEVEL,1          ;Else, indicate had a problem.
  523.                MOV    SI,DX                  ;Display filename and message
  524.                CALL   DISPLAY_TEXT           ; if file not found.
  525.                MOV    SI,OFFSET NOT_FOUND
  526.                CALL   DISPLAY_TEXT
  527.                RET
  528.  
  529. GOT_FILE:      MOV    BX,AX                  ;Filehandle in BX.
  530. NEXT_READ:     CALL   READ_IT                ;Read it.
  531.                JC     CLOSE_FILE             ;Done here if nothing read.
  532.                CALL   CK_SPACE               ;If room, read balance, if any,
  533.                JNC    NEXT_READ              ; into next page.
  534.  
  535. CLOSE_FILE:    MOV    AH,3EH                 ;Close file.
  536.                INT    21H
  537. END_READ:      RET
  538.  
  539. ;--------------------------------------------------------------------;
  540. ; This subroutine does the actual reading of help files into storage ;
  541. ;--------------------------------------------------------------------;
  542.  
  543. READ_IT:       MOV    CL,PAGE_COUNT          ;Retrieve page count.
  544.                CALL   PAGE_SIZE              ;Convert to offset.
  545.                PUSH   ES
  546.                POP    DS                     ;Point to storage segment.
  547.                MOV    CX,4000                ;Read 4000 bytes.
  548.                MOV    AH,3FH
  549.                INT    21H
  550.                JC     READ_END
  551.                CMP    AX,0                   ;Did we read anything?
  552.                JZ     READ_END
  553.                INC    CS:PAGE_COUNT          ;If yes, increment page count.
  554.                SUB    CX,AX                  ;Was it a full page?
  555.                JZ     SKIP_PAD
  556.                MOV    DI,DX                  ;If no, pad balance with nulls.
  557.                ADD    DI,AX
  558.                XOR    AL,AL
  559.                REP    STOSB
  560. SKIP_PAD:      CLC                           ;Indicate read something.
  561.                JMP    SHORT RESTORE_DS
  562.  
  563. READ_END:      STC                           ;Indicate nothing read.
  564. RESTORE_DS:    PUSH   CS                     ;Restore data segment.
  565.                POP    DS
  566.                RET
  567.  
  568. ;------------------------------------------------;
  569. ; This subroutine checks for free storage space. ;
  570. ;------------------------------------------------;
  571.  
  572. CK_SPACE:      CMP    PAGE_COUNT,14          ;Already a full 14 pages?
  573.                JZ     NO_SPACE               ;If yes, no space.
  574.                CMP    INSTALLED_FLAG,1       ;Are we installed.
  575.                JNZ    SPACE
  576.                MOV    AL,ES:RESERVED_PAGES   ;If yes, are reserved pages full?
  577.                CMP    AL,PAGE_COUNT
  578.                JZ     NO_SPACE               ;If yes, no space.
  579. SPACE:         CLC                           ;Else, there is space.
  580.                RET
  581.  
  582. NO_SPACE:      STC
  583.                RET
  584.  
  585. ;-------------------------------------------------------;
  586. ; This subroutine calculates the page offsets.          ;
  587. ; Enter with CL = multiplicand; Return with DX = offset ;
  588. ;-------------------------------------------------------;
  589.  
  590. PAGE_SIZE:     MOV    AX,4000                ;Multiply by 4000 bytes.
  591.                XOR    DX,DX
  592.                XOR    CH,CH
  593.                MUL    CX
  594.                MOV    DX,OFFSET PAGE_BUFFER  ;Add to page buffer offset.
  595.                ADD    DX,AX
  596.                RET
  597.  
  598. ;------------------------------------------;
  599. ; This subroutine converts decimal to hex. ;
  600. ;------------------------------------------;
  601.  
  602. DEC_TO_HEX:    XOR    BL,BL                  ;Start with zero.
  603. NEXT_NUMBER:   LODSB                         ;Get a byte.
  604.                CMP    AL,"0"                 ;Is it a number?
  605.                JB     END_NUMBER
  606.                CMP    AL,"9"
  607.                JA     END_NUMBER
  608.                SUB    AL,"0"                 ;If yes convert to hex.
  609.                XCHG   AL,BL                  ;Save it.
  610.                XOR    AH,AH                  ;Multiply previous by 10.
  611.                MOV    DL,10
  612.                MUL    DL
  613.                XCHG   AL,BL                  ;Retrieve current number.
  614.                ADD    BL,AL                  ;And add to total.
  615.                JMP    SHORT NEXT_NUMBER
  616. END_NUMBER:    DEC    SI                     ;Adjust pointer.
  617.                RET
  618.  
  619. ;---------------------------------------------------------;
  620. ; This subroutine checks the command line for delimiters. ;
  621. ;---------------------------------------------------------;
  622.  
  623. CK_DELIMITER:  LODSB                         ;Get a byte.
  624.                MOV    DI,OFFSET DELIMITERS   ;Point to delimiters.
  625.                MOV    CX,6
  626.                REPNZ  SCASB                  ;And see if match.
  627.                JNZ    NO_DELIMITER
  628.                MOV    BYTE PTR [SI-1],0      ;If yes, convert to ASCIIZ.
  629.                STC
  630.                RET
  631. NO_DELIMITER:  CLC
  632.                RET
  633.  
  634. ;-------------------------------------------------;
  635. ; This subroutine capitalizes the character in AL ;
  636. ;-------------------------------------------------;
  637.  
  638. CAPITALIZE:    CMP    AL,"a"
  639.                JB     END_CAPS
  640.                CMP    AL,"z"
  641.                JA     END_CAPS
  642.                AND    AL,5FH
  643. END_CAPS:      RET
  644.  
  645. ;------------------------------------------------------------------;
  646. ; This subroutine stores the screen so it can be restored on exit. ;
  647. ;------------------------------------------------------------------;
  648.  
  649. STORE_SCREEN:  MOV    LINE_COUNT,25          ;25 lines to save.
  650.                MOV    DX,STATUS_REG          ;Retrieve status register.
  651.                MOV    AX,SCREEN_SEG          ;Point to screen buffer.
  652.                MOV    DS,AX
  653.                PUSH   CS                     ;Point to storage segment.
  654.                POP    ES
  655.                XOR    SI,SI                        ;Top left corner.
  656.                MOV    DI,OFFSET SCREEN_BUFFER      ;Point to storage offset.
  657.  
  658. NEXT_LINE1:    MOV    BP,ES:CRT_COLS         ;Retrieve screen columns.
  659.                MOV    CX,80                  ;Save maximum of 80 columns.
  660.  
  661. HORZ_RET1:     IN     AL,DX                  ;Get status.
  662.                TEST   AL,1                   ;Is it low?
  663.                JNZ    HORZ_RET1              ;If no, wait until it is.
  664.                CLI                           ;No more interrupts.
  665.  
  666. WAIT1:         IN     AL,DX                  ;Get status
  667.                TEST   AL,1                   ;Is it high?
  668.                JZ     WAIT1                  ;If no, wait until it is.
  669.                LODSW                         ;Retrieve a word.
  670.                STI                           ;Interrupts back on.
  671.                STOSW                         ;Store the character/attribute.
  672.  
  673.                DEC    BP                     ;Decrement screen column count.
  674.                JZ     SHORT_COLS1            ;Was it less than 80?
  675.                LOOP   HORZ_RET1              ;If no, loop until row done.
  676.  
  677.                SHL    BP,1                   ;Convert balance to a word.
  678.                ADD    SI,BP                  ;Add to screen offset.
  679.                JMP    SHORT CK_LINES1
  680.  
  681. SHORT_COLS1:   DEC    CX                     ;Adjust balance.
  682.                SHL    CX,1                   ;Convert to a word.
  683.                ADD    DI,CX                  ;Add to storage offset.
  684.  
  685. CK_LINES1:     DEC    ES:LINE_COUNT          ;Do all 25 lines.
  686.                JNZ    NEXT_LINE1
  687.  
  688.                PUSH   CS                     ;Restore data segment.
  689.                POP    DS
  690.                RET                           ;Return.
  691.  
  692. ;---------------------------------------------;
  693. ; This subroutine writes to the screen buffer ;
  694. ;---------------------------------------------;
  695.  
  696. WRITE_SCREEN:  MOV    LINE_COUNT,25          ;25 lines to save.
  697.                MOV    DX,STATUS_REG          ;Retrieve status register.
  698.                MOV    AX,SCREEN_SEG          ;Point to screen buffer.
  699.                MOV    ES,AX
  700.                XOR    DI,DI                  ;Top left corner.
  701.  
  702. NEXT_LINE2:    MOV    BP,CRT_COLS            ;Retrieve screen columns.
  703.                MOV    CX,80                  ;Write maximum of 80 columns.
  704.  
  705. NEXT_BYTE:     LODSW                         ;Get a byte.
  706.                MOV    BX,AX                  ;Store it in AX.
  707.  
  708. HORZ_RET2:     IN     AL,DX                  ;Get status.
  709.                TEST   AL,1                   ;Is it low?
  710.                JNZ    HORZ_RET2              ;If no, wait until it is.
  711.                CLI                           ;No more interrupts.
  712.  
  713. WAIT2:         IN     AL,DX                  ;Get status.
  714.                TEST   AL,1                   ;Is it high?
  715.                JZ     WAIT2                  ;If no, wait until it is.
  716.                MOV    AX,BX                  ;Retrieve the word
  717.                STOSW                         ; and store it.
  718.                STI                           ;Interrupts back on.
  719.  
  720.                DEC    BP                     ;Decrement screen column count.
  721.                JZ     SHORT_COLS2            ;Was it less than 80?
  722.                LOOP   NEXT_BYTE              ;If no, loop until row done.
  723.  
  724.                SHL    BP,1                   ;Convert balance to a word.
  725.                ADD    DI,BP                  ;Add to storage offset.
  726.                JMP    SHORT CK_LINES2
  727.  
  728. SHORT_COLS2:   DEC    CX                     ;Adjust balance.
  729.                SHL    CX,1                   ;Convert to a word.
  730.                ADD    SI,CX                  ;Add to screen offset.
  731.  
  732. CK_LINES2:     DEC    LINE_COUNT             ;Do all 25 lines.
  733.                JNZ    NEXT_LINE2
  734.                RET
  735.  
  736.  
  737. SCREEN_BUFFER  LABEL  BYTE
  738. PAGE_BUFFER    EQU    SCREEN_BUFFER + ( 2 * 80 * 25 )
  739.  
  740. CODE ENDS
  741. END  START
  742.